package com.five.admin.server.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.five.admin.config.RabbitConfig;
import com.five.admin.mapper.OrderMapper;
import com.five.admin.redis.OrderRedisCache;
import com.five.admin.server.OrderItemService;
import com.five.admin.server.ProductService;
import com.five.admin.server.UserOrderService;
import com.five.admin.utils.OrderNoGenerator;
import com.five.admin.cache.OrderCaffeineCache;

import com.five.core.enums.OrderStatusEnum;
import com.five.core.exception.CustomerException;
import com.five.core.result.ResultEnum;
import com.five.event.OrderChangeEvent;
import com.five.pojo.dto.OrderItemDTO;
import com.five.pojo.entity.Order;
import com.five.pojo.entity.OrderItem;
import com.five.pojo.entity.Product;
import com.five.pojo.vo.OrderDetailVO;
import com.five.pojo.vo.OrderDetailVO.OrderItemVO;
import com.five.pojo.vo.OrderListVO;
import com.five.service.CommonOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@DubboService(interfaceClass = CommonOrderService.class)
@Service
@Slf4j
public class UserOrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements UserOrderService, CommonOrderService {

    @Resource
    private OrderItemService orderItemService;
    @Resource
    private ProductService productService;

    @Resource
    private OrderCaffeineCache caffeineCache; // Caffeine本地缓存（当前服务节点）
    @Resource
    private RabbitTemplate rabbitTemplate; // 消息发送（缓存更新通知）

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    private static final String ORDER_CANCEL_LM_KEY = "order:cancel";

    private static final int ORDER_PAY_TIMEOUT_MINUTES = 15;

    /**
     * 创建订单
     */
    @Override
    @Transactional
    public String createOrder(Order order, List<OrderItem> orderItems) {
        if (order == null) {
            throw new CustomerException(ResultEnum.ORDER_ISNULL.getMessage());
        }
        if (CollectionUtils.isEmpty(orderItems)) {
            throw new CustomerException(ResultEnum.ORDER_ITEM_ISNULL.getMessage());
        }

        // 1. 生成订单号
        String orderNo = OrderNoGenerator.generate(order.getUserId());
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatusEnum.UNPAID.getCode());

        // 2. 校验总金额
        BigDecimal itemTotal = BigDecimal.ZERO;
        for (OrderItem item : orderItems) {
            // 确保totalPrice不为null，如果为null则根据productPrice和quantity计算
            BigDecimal itemTotalPrice = item.getTotalPrice();
            if (itemTotalPrice == null) {
                // 如果totalPrice为null，则根据单价和数量计算
                BigDecimal productPrice = item.getProductPrice();
                Integer quantity = item.getQuantity();

                if (productPrice == null || quantity == null) {
                    throw new CustomerException("订单项缺少价格信息: 商品ID=" + item.getProductId());
                }

                itemTotalPrice = productPrice.multiply(new BigDecimal(quantity));
                item.setTotalPrice(itemTotalPrice); // 设置计算后的总价
            }
            itemTotal = itemTotal.add(itemTotalPrice);
        }

        // 确保运费不为null
        BigDecimal freightAmount = order.getFreightAmount();
        if (freightAmount == null) {
            freightAmount = BigDecimal.ZERO;
        }

        BigDecimal totalAmount = itemTotal.add(freightAmount);
        if (totalAmount.compareTo(order.getTotalAmount()) != 0) {
            throw new CustomerException(ResultEnum.TOTAL_AMOUNT_NOT_MATCH.getMessage());
        }
        LocalDateTime now = LocalDateTime.now(); // 获取当前时间

        // 3. 保存订单
        order.setCreateTime(now);
        order.setUpdateTime(now);
        baseMapper.insert(order);
        Long orderId = order.getId();
        orderItems.forEach(item -> {
            item.setOrderId(orderId);
            item.setOrderNo(orderNo);
            item.setCreateTime(now); // 设置创建时间
        });
        orderItemService.saveBatch(orderItems);

        // 4. 发送事件
        sendOrderChangeEvent(orderId, orderNo, order.getUserId(), "CREATE");
        clearLocalCache(order.getUserId(), orderNo);
        log.info("订单创建成功：orderNo={}, userId={}", orderNo, order.getUserId());

        // 5. 缓存订单的id，用于检测订单是否正常支付
        redisTemplate.opsForList().rightPush(ORDER_CANCEL_LM_KEY+orderId,"order:cancel:pay");
        redisTemplate.expire(ORDER_CANCEL_LM_KEY+orderId, Duration.ofMinutes(ORDER_PAY_TIMEOUT_MINUTES));


        return orderNo;
    }

    /**
     * 查询订单详情
     */
    @Override
    public OrderDetailVO getOrderDetail(Long orderId) {
        Order order = baseMapper.selectById(orderId);
        return order != null ? getOrderDetailByNo(order.getOrderNo()) : null;
    }

    /**
     * 订单号查询详情
     */
    @Override
    public OrderDetailVO getOrderDetailByNo(String orderNo) {
        Order order = baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo));
        if (order == null) {
            return null;
        }
        String cacheKey = order.getUserId() + ":" + orderNo;
        OrderDetailVO detailVO = caffeineCache.getOrderDetailCache().get(cacheKey);
        log.info("订单详情查询完成：orderNo={}", orderNo);
        return detailVO;
    }

    /**
     * 取消订单
     */
    @Override
    @Transactional
    public boolean cancelOrder(Long orderId, String cancelReason) {
        Order order = baseMapper.selectByIdForUpdate(orderId);
        if (order == null) {
            log.warn("取消订单失败：订单不存在，orderId={}", orderId);
            return false;
        }
        Long userId = order.getUserId();
        String orderNo = order.getOrderNo();

        if (!OrderStatusEnum.UNPAID.getCode().equals(order.getOrderStatus())) {
            throw new CustomerException(ResultEnum.ORDER_STATUS_NOT_ALLOW_CANCEL.getMessage());
        }

        // 恢复库存
        List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderId, orderId));
        if (CollectionUtils.isNotEmpty(orderItems)) {
            for (OrderItem item : orderItems) {
                int rows = productService.increaseStock(item.getProductId(), item.getQuantity());
                if (rows == 0) {
                    throw new CustomerException("库存恢复失败");
                }
            }
        }

        // 更新状态
        order.setOrderStatus(OrderStatusEnum.CANCELED.getCode());
        order.setCancelTime(LocalDateTime.now());
        order.setRemark(cancelReason);
        int rows = baseMapper.updateById(order);

        if (rows > 0) {
            clearLocalCache(userId, orderNo);
            sendOrderChangeEvent(orderId, orderNo, userId, "CANCEL");
            getOrderDetailByNo(order.getOrderNo());
            log.info("订单取消成功：orderNo={}", orderNo);
        }
        return rows > 0;
    }

    /**
     * 订单支付
     */
    @Override
    @Transactional
    public boolean payOrder(String orderNo, Integer payType) {
        Order order = baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo));
        if (order == null) {
            throw new CustomerException(ResultEnum.ORDER_NOT_EXIST.getMessage()); // 修复异常信息
        }
        Long userId = order.getUserId();

        if (!OrderStatusEnum.UNPAID.getCode().equals(order.getOrderStatus())) {
            throw new CustomerException(ResultEnum.ORDER_STATUS_NOT_ALLOW_PAY.getMessage());
        }

        List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNo, orderNo));
        if (CollectionUtils.isEmpty(orderItems)) {
            throw new CustomerException(ResultEnum.ORDER_ITEM_ISNULL.getMessage());
        }
        for (OrderItem item : orderItems) {
            int rows = productService.reduceStock(item.getProductId(), item.getQuantity());
            if (rows == 0) {
                throw new CustomerException(ResultEnum.STOCK_INSUFFICIENT.getMessage());
            }
        }

        // 更新状态
        order.setOrderStatus(OrderStatusEnum.UNDELIVERED.getCode());
        order.setPayType(payType);
        order.setPayTime(LocalDateTime.now());
        int rows = baseMapper.updateById(order);

        if (rows > 0) {
            clearLocalCache(userId, orderNo);
            sendOrderChangeEvent(order.getId(), orderNo, userId, "PAY");
            getOrderDetailByNo(order.getOrderNo());
            log.info("订单支付成功：orderNo={}", orderNo);
        }
        return rows > 0;
    }
    /**
     * 订单发货
     */
    @Override
    @Transactional
    public boolean deliverOrder(Order order) {

        // 更新状态为已发货
        order.setOrderStatus(2);
        order.setDeliveryTime(LocalDateTime.now());
        order.setOrderStatus(OrderStatusEnum.UNRECEIVED.getCode());
        order.setDeliveryTime(LocalDateTime.now());
        int rows = baseMapper.updateById(order);

        if (rows > 0) {
            clearLocalCache(order.getUserId(), order.getOrderNo());
            sendOrderChangeEvent(order.getId(), order.getOrderNo(), order.getUserId(), "DELIVERY");
            getOrderDetailByNo(order.getOrderNo());
            log.info("订单发货成功：orderNo={}", order.getOrderNo());
        }
        return rows > 0;
    }
    /**
     * 确认收货
     */
    @Override
    @Transactional
    public boolean confirmReceive(Long orderId) {
        Order order = baseMapper.selectById(orderId);
        if (order == null) {
            throw new CustomerException(ResultEnum.ORDER_NOT_EXIST.getMessage()); // 修复异常信息
        }

        if (!OrderStatusEnum.UNRECEIVED.getCode().equals(order.getOrderStatus())) {
            throw new CustomerException(ResultEnum.ORDER_STATUS_NOT_ALLOW_RECEIVE.getMessage());
        }

        // 更新状态
        order.setOrderStatus(OrderStatusEnum.COMPLETED.getCode());
        order.setReceiveTime(LocalDateTime.now());
        int rows = baseMapper.updateById(order);
        System.out.println("rows = " + rows);
        if (rows > 0) {
            clearLocalCache(order.getUserId(), order.getOrderNo());
            sendOrderChangeEvent(orderId, order.getOrderNo(), order.getUserId(), "RECEIVE");
            log.info("订单确认收货成功：orderId={}", orderId);
            getOrderDetailByNo(order.getOrderNo());
        }
        return rows > 0;
    }

    /**
     * 查询用户订单列表
     */
    @Override
    public Page<OrderListVO> getUserOrders(Long userId, Integer pageNum, Integer pageSize) {
        String cacheKey = userId + ":" + pageNum + ":" + pageSize; // 格式：userId:pageNum:pageSize
        return caffeineCache.getOrderListCache().get(cacheKey);
    }

    /**
     * 发送订单变更事件
     */
    public void sendOrderChangeEvent(Long orderId, String orderNo, Long userId, String changeType) {
        try {
            OrderChangeEvent event = new OrderChangeEvent();
            event.setOrderId(orderId);
            event.setOrderNo(orderNo);
            event.setUserId(userId);
            event.setChangeType(changeType);
            rabbitTemplate.convertAndSend(RabbitConfig.ORDER_EVENT_EXCHANGE, "", event);
            log.info("订单变更事件发送成功：{}", event);
        } catch (Exception e) {
            log.error("订单变更事件发送失败", e);
            // 建议补充本地消息表补偿逻辑
        }
    }

    /**
     * 清除当前节点本地缓存
     */
    private void clearLocalCache(Long userId, String orderNo) {
        String detailKey = userId + ":" + orderNo;
        // 清除详情和状态缓存
        caffeineCache.getOrderDetailCache().invalidate(detailKey);
        caffeineCache.getOrderStatusCache().invalidate(detailKey);

        // 清除用户所有分页列表缓存（匹配userId:pageNum:pageSize格式）
        Set<String> listKeys = caffeineCache.getOrderListCache().asMap().keySet().stream()
                .filter(key -> key.startsWith(userId + ":"))
                .collect(Collectors.toSet());
        if (!listKeys.isEmpty()) {
            caffeineCache.getOrderListCache().invalidateAll(listKeys);
        }
        log.info("本地缓存清除完成：userId={}, orderNo={}", userId, orderNo);
    }
}